home *** CD-ROM | disk | FTP | other *** search
- ;------------------------------------------------------------------------;
- ; MONO - TSR designed to make color applications readable on monochrome ;
- ; labtop computers by converting color attributes to monochrome. ;
- ; Syntax: MONO [U] ;
- ; PC Magazine - Michael J. Mefford ;
- ;------------------------------------------------------------------------;
- BIOS_DATA SEGMENT AT 40H
- ORG 17H
- KBD_FLAG DB ?
- ORG 49H
- CRT_MODE DB ?
- CRT_COLS DW ?
- ORG 4EH
- CRT_START DW ?
- ORG 63H
- ADDR_6845 DW ?
- ORG 84H
- CRT_ROWS DB ?
- BIOS_DATA ENDS
-
- _TEXT SEGMENT PUBLIC 'CODE'
- ASSUME CS:_TEXT,DS:_TEXT,ES:_TEXT,SS:_TEXT
- ORG 100H
- START: JMP INITIALIZE
-
- ; DATA AREA
- SIGNATURE DB CR,SPACE,SPACE,SPACE,CR,LF
- COPYRIGHT DB "MONO 1.0 (c) 1989 Ziff Communications Co.",CR,LF
- PROGRAMMER DB "PC Magazine ",BOX," Michael J. Mefford",CR,LF,LF,"$"
- DB CTRL_Z
-
- CR EQU 13
- LF EQU 10
- CTRL_Z EQU 26
- SPACE EQU 32
- BELL EQU 7
- BOX EQU 254
-
- ALT_SHIFT EQU 08H
- PORT_A EQU 60H
- PORT_B EQU 61H
- COMMAND_PORT EQU 20H
- EOI EQU 20H
- M_SCAN_CODE EQU 32H
-
- OLD_INT_8 DW ?,?
- OLD_INT_9 DW ?,?
-
- COUNTER DB 0
- BUSY_FLAG DB 0
- MODE_BYTE DB 1
-
- ; CODE AREA
- ;************* INTERRUPT HANDLERS *************;
-
- MONO_INT_8 PROC FAR
- PUSHF
- ADD CS:COUNTER,64 ;Change attributes every 256/64
- JNB INT_8_END ; timer ticks
- PUSH DS ; (approx. every 1/5 second.)
- PUSH CS
- POP DS ;Point to our data segment.
- CMP BUSY_FLAG,1 ;Are we already adjusting colors?
- JZ RESTORE_SEG ;If yes, exit.
-
- STI ;Else, interrupts on.
- CALL ATTRIBUTES ;Set the attributes.
- RESTORE_SEG: POP DS ;Restore data segment.
-
- INT_8_END: POPF
- JMP DWORD PTR CS:OLD_INT_8 ;Service old INT 8 interrupt.
- MONO_INT_8 ENDP
-
- ;------------------------------------------------;
- MONO_INT_9 PROC FAR
- PUSH AX ;Save some registers.
- PUSHF
- PUSH DS
-
- MOV AX,40H ;Is the Alt key depressed?
- MOV DS,AX
- ASSUME DS:BIOS_DATA
- TEST KBD_FLAG,ALT_SHIFT
- JZ INT_9_END ;If no, exit.
-
- IN AL,PORT_A ;Else, is the "M" key pressed?
- CMP AL,M_SCAN_CODE
- JNZ INT_9_END ;If no, exit.
-
- XOR CS:MODE_BYTE,1 ;Else, toggle active state.
- IN AL,PORT_B ;Retrieve Port B.
- OR AL,80H ;Turn bit 7 on to reset.
- JMP $ + 2 ;I/O delay.
- OUT PORT_B,AL ;Reset KBD.
- AND AL,NOT 80H ;Turn bit 7 back off.
- JMP $ + 2 ;I/O delay.
- OUT PORT_B,AL ;Restore port.
-
- POP DS ;Restore data segment.
- POPF
- CLI ;Interrupts off.
- MOV AL,EOI ;Send End Of Interrupt
- OUT COMMAND_PORT,AL ; to 8259A PIC.
- POP AX ;Restore AX.
- IRET ;Interrupt return.
-
- INT_9_END: POP DS ;No-hot-key exit.
- POPF
- POP AX
- JMP DWORD PTR CS:OLD_INT_9 ;Go to old INT 9 interrupt.
- MONO_INT_9 ENDP
-
- ;-----------------------------------------;
- INACTIVE: RET ;Quick exit.
-
- ASSUME DS:_TEXT
- ATTRIBUTES: CLD ;Strings operations forward.
- CMP MODE_BYTE,0 ;Is attribute mode active?
- JZ INACTIVE ;If no, done here; exit.
- MOV BUSY_FLAG,1 ;Else, flag so non-reentrant.
- PUSH AX ;Save some registers.
- PUSH DS
- MOV AX,40H ;Point to BIOS data segment.
- MOV DS,AX
- ASSUME DS:BIOS_DATA
- MOV AL,CRT_MODE ;Retrieve video mode.
- CMP AL,3 ;Is it color text mode?
- JBE SAVE_REG ;If yes, continue.
- CMP AL,7 ;Is it mono text mode?
- JNZ QUICK_EXIT ;If no, graphics; exit.
-
- SAVE_REG: PUSH BX
- PUSH CX ;Else, save some more registers.
- PUSH DX
- PUSH DI
- PUSH ES
-
- MOV AX,CRT_COLS ;Retrieve CRT columns.
- MOV CL,CRT_ROWS ;Retrieve CRT rows - 1.
- OR CL,CL ;Is in non-zero?
- JNZ DO_CRT_LENGTH ;If yes, good value.
- MOV CL,24 ;Otherwise, use 25 - 1 row value.
- DO_CRT_LENGTH: INC CL ;Adjust row.
- MUL CL ;CRT length = rows * columns.
- MOV CX,AX ;Store in counter.
-
- MOV DX,ADDR_6845 ;Retrieve 6845 address.
- ADD DX,6 ;Convert to Status register.
- MOV DI,CRT_START ;Retrieve start of CRT buffer.
- INC DI ;Point to first attribute.
- MOV AX,0B000H ;Assume mono card segment.
- CMP DX,3BAH ;Is it?
- JZ VIDEO_SEG ;If yes, continue.
- ADD AX,800H ;Else, color card segment.
- VIDEO_SEG: MOV DS,AX ;Set segment registers.
- MOV ES,AX
- MOV BX,7007H ;Inverse video and normal attrib.
- ; Jmp Short SNOW_CHECK ;Add this instruction for CGA.
- NOP ;NOP bytes to add jump to
- NOP ; snow check routine via Debug.
-
- NEXT_ATTRIB: MOV AL,[DI] ;Retrieve an attribute.
- MOV AH,BH ;Assume inverse video.
- TEST AL,AH ;Is background non-zero?
- JNZ ADD_ATTRIB ;If yes, use 70h attribute.
- MOV AH,BL ;Else, use 07h attribute.
- ADD_ATTRIB: AND AL,NOT 77H ;Mask off all but intensity and
- OR AL,AH ; blinking; add attribute.
- STOSB ;Store the attribute.
- INC DI ;Bump pointer past character.
- LOOP NEXT_ATTRIB ;Do all attributes.
- JMP SHORT RESTORE_REG
-
- ;---------------------------------------;
- ; Snow checking routine for CGA cards. ;
- ;---------------------------------------;
- SNOW_CHECK: MOV AH,[DI] ;Retrieve an attribute.
- MOV AL,BH ;Assume inverse video.
- TEST AH,AL ;Is background non-zero?
- JNZ ADD_ATTRIB2 ;If yes, use 70h attribute.
- MOV AL,BL ;Else, use 07h attribute.
- ADD_ATTRIB2: AND AH,NOT 77H ;Mask off all but intensity and
- OR AH,AL ; blinking; add attribute.
-
- HORZ_RET: IN AL,DX ;Get status.
- TEST AL,1 ;Is it low?
- JNZ HORZ_RET ;If not, wait until it is.
- CLI ;No more interrupts.
-
- HWAIT: IN AL,DX ;Get status.
- TEST AL,1 ;Is it high?
- JZ HWAIT ;If no, wait until it is.
- XCHG AL,AH ;Retrieve character; now it's OK
- STOSB ; to write to screen buffer.
- STI ;Interrupts back on.
- INC DI ;Bump pointer past character.
- LOOP SNOW_CHECK ;Do all attributes.
-
- RESTORE_REG: POP ES ;Restore registers.
- POP DI
- POP DX
- POP CX
- POP BX
- ASSUME DS:_TEXT
- QUICK_EXIT: POP DS
- POP AX
- MOV BUSY_FLAG,0 ;No longer busy.
- RET
-
- ; DISPOSABLE DATA
- ; ---------------
- SYNTAX LABEL BYTE
- DB "Syntax: MONO [U]",CR,LF
- DB "U = uninstall",CR,LF
- DB "Hot key = Alt M"
- DB CR,LF,LF,"$"
-
- NOT_INSTALLED DB "MONO not installed",CR,LF,"$"
- UNLOAD_MSG DB "MONO can't uninstall",CR,LF,"$"
- NOT_ENOUGH DB "Not enough memory",CR,LF,"$"
- ALLOCATE_MSG DB "Memory allocation error",CR,LF,BELL,"$"
- INSTALL_MSG DB "Installed",CR,LF,"$"
- UNINSTALL_MSG DB "Uninstalled",CR,LF,"$"
-
- ;--------------------------------------------------------------------;
- ; Search memory for a copy of our code, to see if already installed. ;
- ;--------------------------------------------------------------------;
- INITIALIZE PROC NEAR
- CLD ;All string operations forward.
- MOV BX,OFFSET START ;Point to start of code.
- NOT BYTE PTR [BX] ;Change a byte so no false match.
- XOR DX,DX ;Start at segment zero.
- MOV AX,CS ;Store our segment in AX.
- NEXT_PARAG: INC DX ;Next paragraph.
- MOV ES,DX
- CMP DX,AX ;Is it our segment?
- JZ ANNOUNCE ;If yes, search is done.
- MOV SI,BX ;Else, point to our signature.
- MOV DI,BX ; and offset of possible match.
- MOV CX,16 ;Check 16 bytes for match.
- REP CMPSB
- JNZ NEXT_PARAG ;If no match, keep looking.
-
- ;------------------------------------------------;
- ANNOUNCE: MOV DX,OFFSET SIGNATURE ;Display our signature.
- CALL PRINT_STRING
- MOV DX,OFFSET SYNTAX ;And syntax.
- CALL PRINT_STRING
-
- ;------------------------------------------------;
- PARSE: MOV SI,81H ;Point to command line again.
- NEXT_PARSE: LODSB ;Get a byte.
- CMP AL,CR ;Is it CR?
- JZ INSTALL ;If yes, done here.
- AND AL,5FH
- CMP AL,"U" ;Is it "U" ?
- JNZ NEXT_PARSE ;If no, next byte.
- CALL CK_INSTALLED ;Else, see if installed.
- MOV DX,OFFSET NOT_INSTALLED ;If no, exit with error message.
- JZ MSG_EXIT
- JMP SHORT UNINSTALL ;Else, uninstall.
-
- ;------------------------------------------------;
- INSTALL: CALL CK_INSTALLED ;Check if already installed.
- JZ CK_AVAILABLE ;If no, see if enough memory.
- XOR AL,AL ;Else, done.
- JMP SHORT EXIT ;Exit with ERRORLEVEL = 0.
-
- ;--------------------------------;
- ; This is the install procedure. ;
- ;--------------------------------;
- CK_AVAILABLE: MOV BP,OFFSET SYNTAX ;End of resident portion.
- ADD BP,15 ;Round up.
- CMP BP,DS:[6] ;TSR > PSP bytes in segment?
- MOV DX,OFFSET NOT_ENOUGH ;If yes, exit without installing
- JA MSG_EXIT ; with message.
-
- MOV AX,3508H ;Else, get INT 8 vector.
- INT 21H
- MOV OLD_INT_8[0],BX ;Save old interrupt.
- MOV OLD_INT_8[2],ES
- MOV DX,OFFSET MONO_INT_8 ;Install new interrupt.
- MOV AX,2508H
- INT 21H
-
- MOV AX,3509H ;Get INT 9 vector.
- INT 21H
- MOV OLD_INT_9[0],BX ;Save old interrupt.
- MOV OLD_INT_9[2],ES
- MOV DX,OFFSET MONO_INT_9 ;Install new interrupt.
- MOV AX,2509H
- INT 21H
-
- MOV AX,DS:[2CH] ;Get environment segment.
- MOV ES,AX
- MOV AH,49H ;Free up environment.
- INT 21H
-
- MOV DX,OFFSET INSTALL_MSG ;Display install message.
- CALL PRINT_STRING
- MOV DX,BP ;Retrieve resident request.
- MOV CL,4
- SHR DX,CL ;Convert to paragraphs.
- MOV AX,3100H ;Return error code of zero.
- INT 21H ;Terminate but stay resident.
-
- ;-------------------------------------------------------------------;
- ; Exit. Return ERRORLEVEL code 0 if successful, 1 if unsuccessful. ;
- ;-------------------------------------------------------------------;
- MSG_EXIT: CALL PRINT_STRING
- ERROR_EXIT: MOV AL,1 ;ERRORLEVEL = 1.
- EXIT: MOV AH,4CH ;Terminate.
- INT 21H
-
- ;---------------------------------------------------;
- ; This subroutine uninstalls the resident MONO.COM. ;
- ;---------------------------------------------------;
- UNINSTALL: MOV CX,ES ;Save segment in CX.
- MOV AX,3508H ;Get interrupt 8.
- INT 21H
- CMP BX,OFFSET MONO_INT_8 ;Has it been hooked by another?
- JNZ UNINSTALL_ERR ;If yes, exit with error message.
- MOV BX,ES
- CMP BX,CX ;Is the segment vector same?
- JNZ UNINSTALL_ERR ;If no, exit with error message.
-
- MOV AX,3509H ;Get interrupt 9.
- INT 21H
- CMP BX,OFFSET MONO_INT_9 ;Has it been hooked by another?
- JNZ UNINSTALL_ERR ;If yes, exit with error message.
- MOV BX,ES
- CMP BX,CX ;Is the segment vector same?
- JNZ UNINSTALL_ERR ;If no, exit with error message.
-
- MOV AH,49H ;Return memory to system pool.
- INT 21H
- MOV DX,OFFSET ALLOCATE_MSG
- JC MSG_EXIT ;Display message if problem.
-
- MOV DX,ES:OLD_INT_8[0] ;Restore old INT 8.
- MOV DS,ES:OLD_INT_8[2]
- MOV AX,2508H
- INT 21H
- MOV DX,ES:OLD_INT_9[0] ;Restore old INT 9.
- MOV DS,ES:OLD_INT_9[2]
- MOV AX,2509H
- INT 21H
-
- PUSH CS
- POP DS ;Point to our data.
- MOV DX,OFFSET UNINSTALL_MSG ;Display uninstall message.
- CALL PRINT_STRING
- OR AL,AL ;Exit with ERRORLEVEL = 0.
- JMP EXIT
-
- UNINSTALL_ERR: MOV ES,CX ;If error, exit
- MOV DX,OFFSET UNLOAD_MSG ; with error message.
- JMP MSG_EXIT
- INITIALIZE ENDP
-
- ;-------------------------------------------------------;
- ; OUTPUT: ZR = 1 if not installed; ZR = 0 if installed. ;
- ;-------------------------------------------------------;
- CK_INSTALLED: MOV AX,ES
- MOV BX,CS
- CMP AX,BX ;Compare segments.
- RET
-
- ;------------------------------------------------;
- PRINT_STRING: MOV AH,9
- DOS_INT: INT 21H ;Print string via DOS.
- RET
-
- _TEXT ENDS
- END START
-